package com.karson.service.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.karson.common.exception.AsmrException;
import com.karson.common.exception.ExceptionCodeEnum;
import com.karson.common.model.SystemAdmin;
import com.karson.common.model.SystemMenu;
import com.karson.common.model.SystemMeta;
import com.karson.common.request.MenuRequest;
import com.karson.common.response.MenusResponse;
import com.karson.common.util.MenuTree;
import com.karson.common.util.RedisUtil;
import com.karson.service.dao.SystemAdminMapper;
import com.karson.service.dao.SystemMetaMapper;
import com.karson.service.service.SystemMenuService;
import com.karson.service.dao.SystemMenuMapper;
import com.karson.service.service.SystemMetaService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

/**
* @author ZKS
* @description 针对表【ar_system_menu(系统菜单表)】的数据库操作Service实现
* @createDate 2025-07-04 19:22:33
*/
@Slf4j
@Service
public class SystemMenuServiceImpl extends ServiceImpl<SystemMenuMapper, SystemMenu>
    implements SystemMenuService{

    @Autowired
    private SystemAdminMapper systemAdminMapper;
    @Autowired
    private SystemMenuMapper systemMenuMapper;
    @Autowired
    private SystemMetaMapper systemMetaMapper;
    @Autowired
    private SystemMetaService systemMetaService;
    @Autowired
    private RedisUtil redisUtil;

    private static final String CACHE_LIST_KEY = "menuList";
    @Override
    public List<MenusResponse> getMenu() {
        Object loginId = StpUtil.getLoginId();
        SystemAdmin systemAdmin = systemAdminMapper.selectById(String.valueOf(loginId));
        List<String> roleList = Stream.of(systemAdmin.getRoles().split(",")).toList();
        List<MenusResponse> menuList = List.of();
        if (roleList.contains("1")){
            menuList = systemMenuMapper.findAllCatalogue();
        }
        log.info("查询后菜单列表{}",menuList);
        MenuTree menuTree = new MenuTree(menuList);
        return menuTree.buildTree();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveMenu(MenuRequest menuRequest) {
        SystemMeta meta = menuRequest.getMeta();
        validationMenu(menuRequest);
        LambdaQueryWrapper<SystemMenu> menuQueryWrapper = new LambdaQueryWrapper<>();
        menuQueryWrapper.eq(SystemMenu::getName, menuRequest.getName());
        menuQueryWrapper.or().eq(SystemMenu::getPath, menuRequest.getPath());
        Long count = systemMenuMapper.selectCount(menuQueryWrapper);
        if (count > 0) {
            return false;
        }
        SystemMenu systemMenu = new SystemMenu();
        systemMenu.setPid(menuRequest.getPid());
        systemMenu.setName(menuRequest.getName());
        systemMenu.setPath(menuRequest.getPath());
        systemMenu.setComponent(menuRequest.getComponent());
        systemMenu.setPerms(menuRequest.getPerms());
        systemMenu.setSort(menuRequest.getSort());
        systemMenuMapper.insert(systemMenu);
        Integer menuId = systemMenu.getId();
        meta.setMenuId(menuId);
        int flag = systemMetaMapper.insert(meta);
        if (flag > 0) {
            redisUtil.delete(CACHE_LIST_KEY);
        }
        return true;
    }

    private void validationMenu(MenuRequest menuRequest) {
        SystemMeta meta = menuRequest.getMeta();
        if ("C".equals(meta.getMenuType()) && StrUtil.isEmpty(menuRequest.getComponent())) {
            throw new AsmrException("菜单类型的组件路径不能为空");
        }
        if ("A".equals(meta.getMenuType()) && StrUtil.isEmpty(menuRequest.getPerms())) {
            throw new AsmrException("按钮类型的权限表示不能为空");
        }
        if ("P".equals(meta.getMenuType()) && StrUtil.isEmpty(meta.getLink())) {
            throw new AsmrException("外链类型的权限表示不能为空");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean edit(MenuRequest menuRequest) {
        if (ObjectUtil.isNull(menuRequest.getId())) {
            throw new AsmrException("系统菜单id不能为空");
        }
        validationMenu(menuRequest);
        SystemMenu systemMenu = new SystemMenu();
        BeanUtil.copyProperties(menuRequest, systemMenu);
        boolean updateWithMenu = updateById(systemMenu);
        boolean updateWithMeta = systemMetaService.updateById(menuRequest.getMeta());
        if (updateWithMenu && updateWithMeta) {
            // 清除缓存
           redisUtil.delete(CACHE_LIST_KEY);
        }
        return updateWithMenu && updateWithMeta;
    }
    @Override
    public List<MenusResponse> getCacheTree() {
        if (redisUtil.exists(CACHE_LIST_KEY)) {
            return redisUtil.get(CACHE_LIST_KEY);
        }
        List<MenusResponse> menuList = systemMenuMapper.findAllMenuList();
        MenuTree menuTree = new MenuTree(menuList);
        List<MenusResponse> menusResponses = menuTree.buildTree();
        redisUtil.set(CACHE_LIST_KEY, menusResponses);
        return menusResponses;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteById(Integer id) {
        SystemMenu systemMenu = getById(id);
        LambdaQueryWrapper<SystemMeta> metaQueryWrapper = new LambdaQueryWrapper<>();
        metaQueryWrapper.eq(SystemMeta::getMenuId, id);
        SystemMeta meta = systemMetaService.getOne(metaQueryWrapper);
        systemMenu.setIsDelte(true);
        meta.setIsDelete(true);
        if (ObjectUtil.isNull(systemMenu) || ObjectUtil.isNull(meta)) {
            return false;
        }
        if ("A".equals(meta.getMenuType())) {
            boolean update = updateById(systemMenu);
            boolean metaUpdate = systemMetaService.updateById(meta);
            if (update && metaUpdate) {
                redisUtil.delete(CACHE_LIST_KEY);
            }
            return update && metaUpdate;
        }
        List<MenusResponse> Menus = findAllChildListByPid(id);
        List<SystemMenu> childList = new ArrayList<>();
        List<SystemMeta> metaList = new ArrayList<>();
        if (CollUtil.isEmpty(Menus)) {
            boolean update = updateById(systemMenu);
            boolean metaUpdate = systemMetaService.updateById(meta);
            if (update && metaUpdate) {
                redisUtil.delete(CACHE_LIST_KEY);
            }
            return update && metaUpdate;
        }
        Menus.forEach(e -> {
            SystemMenu child = new SystemMenu();
            child.setId(e.getId());
            child.setPid(e.getPid());
            child.setName(e.getName());
            child.setPath(e.getPath());
            child.setComponent(e.getComponent());
            child.setPerms(e.getPerms());
            child.setSort(e.getSort());
            child.setIsDelte(true);
            e.getMeta().setIsDelete(true);
            metaList.add(e.getMeta());
            childList.add(child);
        });
        boolean updateWithMenu = updateBatchById(childList);
        boolean updateWithMeta = systemMetaService.updateBatchById(metaList);
        if (updateWithMenu && updateWithMeta) {
            redisUtil.delete(CACHE_LIST_KEY);
        }
        return updateWithMenu && updateWithMeta;
    }
    /**
     * 根据菜单id获取所有下级对象 及其拓展属性
     * @param pid 菜单id
     * @return List<MenusResponse>
     */
    private List<MenusResponse> findAllChildListByPid(Integer pid) {
        return systemMenuMapper.findAllChildListByPid(pid);
    }
}




